home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1997 April / EnigmA AMIGA RUN 17 (1997)(G.R. Edizioni)(IT)[!][issue 1997-04][EAR-CD].iso / EARCD / comm / term / term_47a_pch.lha / Source / term-4.7a / Serial.c < prev    next >
C/C++ Source or Header  |  1996-11-05  |  26KB  |  1,333 lines

  1. /*
  2. **    Serial.c
  3. **
  4. **    Serial driver support routines
  5. **
  6. **    Copyright © 1990-1996 by Olaf `Olsen' Barthel
  7. **        All Rights Reserved
  8. **
  9. **    :ts=4
  10. */
  11.  
  12. #ifndef _GLOBAL_H
  13. #include "Global.h"
  14. #endif
  15.  
  16.     /* In case the DSR test is enabled */
  17.  
  18. STATIC BOOL UseRTS_CTS;
  19.  
  20.     /* Serial write output routines */
  21.  
  22. STATIC SERWRITE SerWriteRoutine,SerWriteAndProcessRoutine;
  23.  
  24. STATIC VOID
  25. WriteAndProcessUserMon(APTR Buffer,LONG Size)
  26. {
  27.     Size = XProtocolUserMon(XprIO,Buffer,Size,Size);
  28.  
  29.     if(Size > 0)
  30.     {
  31.         StartSerialWrite(Buffer,Size);
  32.  
  33.         if(Marking)
  34.             WindowMarkerStop();
  35.  
  36.         ConProcess(Buffer,Size);
  37.  
  38.         WaitSerialWrite();
  39.  
  40.         BytesOut += Size;
  41.     }
  42. }
  43.  
  44. STATIC VOID
  45. WriteUserMon(APTR Buffer,LONG Size)
  46. {
  47.     Size = XProtocolUserMon(XprIO,Buffer,Size,Size);
  48.  
  49.     if(Size > 0)
  50.     {
  51.         DoSerialWrite(Buffer,Size);
  52.  
  53.         BytesOut += Size;
  54.     }
  55. }
  56.  
  57. STATIC VOID
  58. WriteAndProcessBypass(APTR Buffer,LONG Size)
  59. {
  60.     if((*SerWriteBypass)(Buffer,Size))
  61.     {
  62.         StartSerialWrite(Buffer,Size);
  63.  
  64.         ConProcess(Buffer,Size);
  65.  
  66.         WaitSerialWrite();
  67.  
  68.         BytesOut += Size;
  69.     }
  70. }
  71.  
  72. STATIC VOID
  73. WriteBypass(APTR Buffer,LONG Size)
  74. {
  75.     if((*SerWriteBypass)(Buffer,Size))
  76.     {
  77.         DoSerialWrite(Buffer,Size);
  78.  
  79.         BytesOut += Size;
  80.     }
  81. }
  82.  
  83. STATIC VOID
  84. WriteAndProcessBypassUserMon(APTR Buffer,LONG Size)
  85. {
  86.     if((*SerWriteBypass)(Buffer,Size))
  87.     {
  88.         Size = XProtocolUserMon(XprIO,Buffer,Size,Size);
  89.  
  90.         if(Size > 0)
  91.         {
  92.             StartSerialWrite(Buffer,Size);
  93.  
  94.             ConProcess(Buffer,Size);
  95.  
  96.             WaitSerialWrite();
  97.  
  98.             BytesOut += Size;
  99.         }
  100.     }
  101. }
  102.  
  103. STATIC VOID
  104. WriteBypassUserMon(APTR Buffer,LONG Size)
  105. {
  106.     if((*SerWriteBypass)(Buffer,Size))
  107.     {
  108.         Size = XProtocolUserMon(XprIO,Buffer,Size,Size);
  109.  
  110.         if(Size > 0)
  111.         {
  112.             DoSerialWrite(Buffer,Size);
  113.  
  114.             BytesOut += Size;
  115.         }
  116.     }
  117. }
  118.  
  119.     /* WriteAndProcess(APTR Buffer,LONG Size):
  120.      *
  121.      *    At the same time write data to the serial port and
  122.      *    process it on the screen.
  123.      */
  124.  
  125. STATIC VOID
  126. WriteAndProcess(APTR Buffer,LONG Size)
  127. {
  128.     StartSerialWrite(Buffer,Size);
  129.  
  130.     ConProcess(Buffer,Size);
  131.  
  132.     WaitSerialWrite();
  133.  
  134.     BytesOut += Size;
  135. }
  136.  
  137.     /* WriteDirect(APTR Buffer,LONG Size):
  138.      *
  139.      *    Output the data and update the byte counter.
  140.      */
  141.  
  142. STATIC VOID
  143. WriteDirect(APTR Buffer,LONG Size)
  144. {
  145.     DoSerialWrite(Buffer,Size);
  146.  
  147.     BytesOut += Size;
  148. }
  149.  
  150.     /* SetFlags():
  151.      *
  152.      *    Set the contents of a serial device request according
  153.      *    to the current configuration settings.
  154.      */
  155.  
  156. STATIC BYTE
  157. SetFlags(VOID)
  158. {
  159.     return(SetBothSerialAttributes(
  160.         SERA_Baud,            Config->SerialConfig->BaudRate,
  161.         SERA_BreakTime,        Config->SerialConfig->BreakLength,
  162.         SERA_BitsPerChar,    Config->SerialConfig->BitsPerChar,
  163.         SERA_StopBits,        Config->SerialConfig->StopBits,
  164.         SERA_BufferSize,    Config->SerialConfig->SerialBufferSize,
  165.         SERA_Parity,        Config->SerialConfig->Parity,
  166.         SERA_Handshaking,    UseRTS_CTS ? Config->SerialConfig->HandshakingProtocol : HANDSHAKING_NONE,
  167.         SERA_HighSpeed,        Config->SerialConfig->HighSpeed,
  168.         SERA_Shared,        Config->SerialConfig->Shared,
  169.     TAG_DONE));
  170. }
  171.  
  172.     /* SendBreak():
  173.      *
  174.      *    Transmit a break signal.
  175.      */
  176.  
  177. VOID
  178. SendBreak()
  179. {
  180.     PushStatus(STATUS_BREAKING);
  181.  
  182.     DoSerialCmd(SDCMD_BREAK);
  183.  
  184.     PopStatus();
  185. }
  186.  
  187.     /* HangUp():
  188.      *
  189.      *    Hang up the line.
  190.      */
  191.  
  192. VOID
  193. HangUp()
  194. {
  195.     PushStatus(STATUS_HANGUP);
  196.  
  197.     StopSerialWrite();
  198.  
  199.         /* Are we to drop the DTR line
  200.          * before sending the hangup
  201.          * string?
  202.          */
  203.  
  204.     if(Config->ModemConfig->DropDTR)
  205.     {
  206.         if(!DropDTR(Config->SerialConfig->SerialDevice,Config->SerialConfig->UnitNumber))
  207.         {
  208.             DeleteSerial();
  209.  
  210.             if(!ShowRequest(Window,LocaleString(MSG_TERMMAIN_FAILED_TO_REOPEN_UNIT_TXT),LocaleString(MSG_TERMMAIN_IGNORE_QUIT_TXT),Config->SerialConfig->SerialDevice,Config->SerialConfig->UnitNumber))
  211.                 MainTerminated = TRUE;
  212.         }
  213.     }
  214.  
  215.         /* Transmit the hangup command. */
  216.  
  217.     if(Config->ModemConfig->ModemHangup[0] && !MainTerminated)
  218.         SerialCommand(Config->ModemConfig->ModemHangup);
  219.  
  220.         /* Reset to old status. */
  221.  
  222.     PopStatus();
  223. }
  224.  
  225.     /* CopyWriteFlags():
  226.      *
  227.      *    Update configuration with serial settings.
  228.      */
  229.  
  230. VOID
  231. CopyWriteFlags()
  232. {
  233.     ULONG    Baud,
  234.             BreakTime,
  235.             BitsPerChar,
  236.             StopBits,
  237.             BufferSize,
  238.             Parity,
  239.             Handshaking,
  240.             HighSpeed,
  241.             Shared;
  242.  
  243.     GetSerialWriteAttributes(
  244.         SERA_Baud,            &Baud,
  245.         SERA_BreakTime,        &BreakTime,
  246.         SERA_BitsPerChar,    &BitsPerChar,
  247.         SERA_StopBits,        &StopBits,
  248.         SERA_BufferSize,    &BufferSize,
  249.         SERA_Parity,        &Parity,
  250.         SERA_Handshaking,    &Handshaking,
  251.         SERA_HighSpeed,        &HighSpeed,
  252.         SERA_Shared,        &Shared,
  253.     TAG_DONE);
  254.  
  255.     Config->SerialConfig->BaudRate                = Baud;
  256.     Config->SerialConfig->BreakLength            = BreakTime;
  257.     Config->SerialConfig->BitsPerChar            = BitsPerChar;
  258.     Config->SerialConfig->StopBits                = StopBits;
  259.     Config->SerialConfig->SerialBufferSize        = BufferSize;
  260.     Config->SerialConfig->Parity                = Parity;
  261.     Config->SerialConfig->HandshakingProtocol    = Handshaking;
  262.     Config->SerialConfig->HighSpeed                = HighSpeed;
  263.     Config->SerialConfig->Shared                = Shared;
  264. }
  265.  
  266.     /* SerWriteVerbatim(APTR Buffer,LONG Size,BOOL Echo):
  267.      *
  268.      *    The `no fancy features' version of SerWrite().
  269.      */
  270.  
  271. VOID
  272. SerWriteVerbatim(APTR Buffer,LONG Size,BOOL Echo)
  273. {
  274.     if(XProtocolBase && (TransferBits & XPRS_USERMON))
  275.         Size = XProtocolUserMon(XprIO,Buffer,Size,Size);
  276.  
  277.     if(Size > 0)
  278.     {
  279.         if(Echo)
  280.             WriteAndProcess(Buffer,Size);
  281.         else
  282.             DoSerialWrite(Buffer,Size);
  283.  
  284.         BytesOut += Size;
  285.     }
  286. }
  287.  
  288.     /* SerWriteUpdate():
  289.      *
  290.      *    Choose the right data output routine for the job.
  291.      */
  292.  
  293. VOID
  294. SerWriteUpdate()
  295. {
  296.     if(SerWriteBypass)
  297.     {
  298.         if(XProtocolBase && (TransferBits & XPRS_USERMON))
  299.         {
  300.             SerWriteRoutine = (SERWRITE)WriteBypassUserMon;
  301.             SerWriteAndProcessRoutine = (SERWRITE)WriteAndProcessBypassUserMon;
  302.         }
  303.         else
  304.         {
  305.             SerWriteRoutine = (SERWRITE)WriteBypass;
  306.             SerWriteAndProcessRoutine = (SERWRITE)WriteAndProcessBypass;
  307.         }
  308.     }
  309.     else
  310.     {
  311.         if(XProtocolBase && (TransferBits & XPRS_USERMON))
  312.         {
  313.             SerWriteRoutine = (SERWRITE)WriteUserMon;
  314.             SerWriteAndProcessRoutine = (SERWRITE)WriteAndProcessUserMon;
  315.         }
  316.         else
  317.         {
  318.             SerWriteRoutine = (SERWRITE)WriteDirect;
  319.             SerWriteAndProcessRoutine = (SERWRITE)WriteAndProcess;
  320.         }
  321.     }
  322. }
  323.  
  324.     /* SerWrite(APTR Buffer,LONG Size):
  325.      *
  326.      *    Send a number of bytes across the serial line.
  327.      */
  328.  
  329. VOID
  330. SerWrite(APTR Buffer,LONG Size)
  331. {
  332.     if(Size < 0)
  333.         Size = strlen(Buffer);
  334.  
  335.     if(Size > 0)
  336.     {
  337.         if(RememberInput)
  338.         {
  339.             RememberInputText(Buffer,Size);
  340.  
  341.             if(((UBYTE *)Buffer)[Size - 1] == '\r' && RecordingLine)
  342.             {
  343.                 RememberSpill();
  344.  
  345.                 RecordingLine = FALSE;
  346.  
  347.                 RememberOutput = TRUE;
  348.                 RememberInput = FALSE;
  349.  
  350.                 CheckItem(MEN_RECORD_LINE,FALSE);
  351.             }
  352.         }
  353.         else
  354.         {
  355.             if(RememberOutput)
  356.             {
  357.                 RememberInputText(Buffer,Size);
  358.  
  359.                 RememberSpill();
  360.             }
  361.         }
  362.  
  363.         if(WriteRequest)
  364.         {
  365.             if(SendTable)
  366.             {
  367.                 struct TranslationHandle Handle;
  368.                 UBYTE TranslateData[256];
  369.  
  370.                     /* Set up for buffer translation. */
  371.  
  372.                 TranslateSetup(&Handle,Buffer,Size,TranslateData,sizeof(TranslateData),SendTable);
  373.  
  374.                     /* Full or half duplex? */
  375.  
  376.                 if(Config->SerialConfig->Duplex == DUPLEX_FULL)
  377.                 {
  378.                         /* Process the data... */
  379.  
  380.                     while(Size = TranslateBuffer(&Handle))
  381.                         (*SerWriteRoutine)(TranslateData,Size);
  382.                 }
  383.                 else
  384.                 {
  385.                     while(Size = TranslateBuffer(&Handle))
  386.                         (*SerWriteAndProcessRoutine)(TranslateData,Size);
  387.                 }
  388.             }
  389.             else
  390.             {
  391.                 if(Config->SerialConfig->Duplex == DUPLEX_FULL)
  392.                     (*SerWriteRoutine)(Buffer,Size);
  393.                 else
  394.                     (*SerWriteAndProcessRoutine)(Buffer,Size);
  395.             }
  396.         }
  397.     }
  398. }
  399.  
  400.     /* RestartSerial():
  401.      *
  402.      *    Restart read/write activity on the serial line.
  403.      */
  404.  
  405. VOID
  406. RestartSerial()
  407. {
  408.         /* Blow away the cache if there is anything left of it. */
  409.  
  410.     if(DataHold)
  411.     {
  412.         DataHold = NULL;
  413.  
  414.         UpdateSerialJob();
  415.     }
  416.  
  417.     StartSerialRead(&ReadChar,1);
  418. }
  419.  
  420.     /* ClearSerial():
  421.      *
  422.      *    Terminate all read/write activity on the serial line.
  423.      */
  424.  
  425. VOID
  426. ClearSerial()
  427. {
  428.         /* Blow away the cache if there is anything left of it. */
  429.  
  430.     if(DataHold)
  431.     {
  432.         DataHold = NULL;
  433.  
  434.         UpdateSerialJob();
  435.     }
  436.  
  437.     StopSerialRead();
  438.  
  439.     FlushSerialRead();
  440. }
  441.  
  442.     /* DeleteSerial():
  443.      *
  444.      *    Close the serial device and release all associated
  445.      *    resources.
  446.      */
  447.  
  448. VOID
  449. DeleteSerial()
  450. {
  451.     StopSerialRead();
  452.     StopSerialWrite();
  453.  
  454.     if(ReadRequest)
  455.     {
  456.         if(ReadRequest->IOSer.io_Device)
  457.         {
  458.             UBYTE Name[MAX_FILENAME_LENGTH];
  459.             struct Device *Device;
  460.  
  461.                 /* Unless the device was opened in shared */
  462.                 /* access mode we'll reset it here */
  463.  
  464.             if(!Config->SerialConfig->Shared)
  465.             {
  466.                 ReadRequest->IOSer.io_Command = CMD_RESET;
  467.  
  468.                 DoIO((struct IORequest *)ReadRequest);
  469.             }
  470.  
  471.                 /* Remember the device name, we'll need it after */
  472.                 /* closing time */
  473.  
  474.             LimitedStrcpy(sizeof(Name),Name,ReadRequest->IOSer.io_Device->dd_Library.lib_Node.ln_Name);
  475.  
  476.                 /* Close the device */
  477.  
  478.             CloseDevice((struct IORequest *)ReadRequest);
  479.  
  480.                 /* And remove it from memory */
  481.  
  482.             Forbid();
  483.  
  484.             if(Device = (struct Device *)FindName(&SysBase->DeviceList,Name))
  485.                 RemDevice(Device);
  486.  
  487.             Permit();
  488.         }
  489.  
  490.         DeleteIORequest(ReadRequest);
  491.         ReadRequest = NULL;
  492.     }
  493.  
  494.     if(WriteRequest)
  495.     {
  496.         DeleteIORequest(WriteRequest);
  497.         WriteRequest = NULL;
  498.     }
  499.  
  500.     if(WritePort)
  501.     {
  502.         DeleteMsgPort(WritePort);
  503.         WritePort = NULL;
  504.     }
  505.  
  506.     if(ReadPort)
  507.     {
  508.         DeleteMsgPort(ReadPort);
  509.         ReadPort = NULL;
  510.     }
  511.  
  512.     FreeVecPooled(ReadBuffer);
  513.     ReadBuffer = NULL;
  514.  
  515.     FreeVecPooled(HostReadBuffer);
  516.     HostReadBuffer = NULL;
  517.  
  518.     FreeVecPooled(StripBuffer);
  519.     StripBuffer = NULL;
  520.  
  521.     UnlockDevice();
  522.  
  523.     UpdateSerialJob();
  524. }
  525.  
  526.     /* GetSerialError(LONG Error,BOOL *Reset):
  527.      *
  528.      *    Return an error message for each possible serial device error.
  529.      */
  530.  
  531. STRPTR
  532. GetSerialError(LONG Error,BOOL *ResetPtr)
  533. {
  534.     BOOL Reset;
  535.     LONG ID;
  536.  
  537.     Reset    = FALSE;
  538.     ID        = -1;
  539.  
  540.     switch(Error)
  541.     {
  542.         case IOERR_BADLENGTH:
  543.         case IOERR_BADADDRESS:
  544.         case IOERR_SELFTEST:
  545.         case IOERR_OPENFAIL:
  546.  
  547.             ID = MSG_SERIAL_OPENFAILURE_TXT;
  548.             break;
  549.  
  550.         case SerErr_DevBusy:
  551.  
  552.             ID = MSG_SERIAL_ERROR_DEVBUSY_TXT;
  553.             break;
  554.  
  555.         case SerErr_BaudMismatch:
  556.         case 3:                        /* MultiFaceCard duart.device uses this. */
  557.  
  558.             Reset = TRUE;
  559.             ID = MSG_SERIAL_ERROR_BAUDMISMATCH_TXT;
  560.             break;
  561.  
  562.         case SerErr_BufErr:
  563.  
  564.             Reset = TRUE;
  565.             ID = MSG_SERIAL_ERROR_BUFERR_TXT;
  566.             break;
  567.  
  568.         case SerErr_InvParam:
  569.  
  570.             Reset = TRUE;
  571.             ID = MSG_SERIAL_ERROR_INVPARAM_TXT;
  572.             break;
  573.  
  574.         case SerErr_LineErr:
  575.  
  576.             ID = MSG_SERIAL_ERROR_LINEERR_TXT;
  577.             break;
  578.  
  579.         case SerErr_ParityErr:
  580.  
  581.             Reset = TRUE;
  582.             ID = MSG_SERIAL_ERROR_PARITYERR_TXT;
  583.             break;
  584.  
  585.         case SerErr_TimerErr:
  586.  
  587.             ID = MSG_SERIAL_ERROR_TIMERERR_TXT;
  588.             break;
  589.  
  590.         case SerErr_BufOverflow:
  591.  
  592.             Reset = TRUE;
  593.             ID = MSG_SERIAL_ERROR_BUFOVERFLOW_TXT;
  594.             break;
  595.  
  596.         case SerErr_NoDSR:
  597.  
  598.             ID = MSG_SERIAL_ERROR_NODSR_TXT;
  599.             break;
  600.  
  601.     /*    case SerErr_UnitBusy:    */
  602.         case IOERR_UNITBUSY:
  603.         case 16:
  604.  
  605.             ID = MSG_SERIAL_ERROR_UNIT_BUSY_TXT;
  606.             break;
  607.     }
  608.  
  609.     if(ID != -1)
  610.     {
  611.         if(ResetPtr)
  612.             *ResetPtr = Reset;
  613.  
  614.         return(LocaleString(ID));
  615.     }
  616.     else
  617.         return(NULL);
  618. }
  619.  
  620.     /* CreateSerial():
  621.      *
  622.      *    Create handles for the serial device and open it.
  623.      */
  624.  
  625. BOOL
  626. CreateSerial(STRPTR ErrorBuffer,LONG ErrorBufferSize)
  627. {
  628.     BYTE Error = 0;
  629.     LONG ID = -1;
  630.  
  631.         /* Try to lock the serial device driver if necessary */
  632.  
  633.     if(Config->SerialConfig->UseOwnDevUnit && !(Config->SerialConfig->Shared && Config->SerialConfig->NoODUIfShared))
  634.     {
  635.         if(!LockDevice(Config->SerialConfig->SerialDevice,Config->SerialConfig->UnitNumber,ErrorBuffer,ErrorBufferSize))
  636.             return(FALSE);
  637.     }
  638.  
  639.         /* Propagate the serial read buffer size to the translation routines */
  640.  
  641.     Update_CR_LF_Translation();
  642.  
  643.         /* Now allocate the required resources... */
  644.  
  645.     if(ReadBuffer = AllocVecPooled(Config->SerialConfig->SerialBufferSize,MEMF_ANY))
  646.     {
  647.         if(StripBuffer = AllocVecPooled(Config->SerialConfig->SerialBufferSize,MEMF_ANY))
  648.         {
  649.             if(XProtocolBase && (TransferBits & XPRS_HOSTNOWAIT))
  650.                 HostReadBuffer = AllocVecPooled(Config->SerialConfig->SerialBufferSize,MEMF_ANY);
  651.  
  652.             if(ReadPort = (struct MsgPort *)CreateMsgPort())
  653.             {
  654.                 if(ReadRequest = (struct IOExtSer *)CreateIORequest(ReadPort,sizeof(struct IOExtSer)))
  655.                 {
  656.                     if(WritePort = (struct MsgPort *)CreateMsgPort())
  657.                     {
  658.                         if(WriteRequest = (struct IOExtSer *)CreateIORequest(WritePort,sizeof(struct IOExtSer)))
  659.                         {
  660.                                 /* Unless the user doesn't want RTS/CTS handshaking */
  661.                                 /* we'll assume it should be enabled. This also concerns */
  662.                                 /* the RTS/CTS+DSR test mode which will also start */
  663.                                 /* with having RTS/CTS handshaking enabled. */
  664.  
  665.                             UseRTS_CTS = (BOOL)(Config->SerialConfig->HandshakingProtocol != HANDSHAKING_NONE);
  666.  
  667.                                 /* Set the default opening parameters */
  668.  
  669.                             SetSerialReadAttributes(
  670.                                 SERA_Baud,            Config->SerialConfig->BaudRate,
  671.                                 SERA_BreakTime,        Config->SerialConfig->BreakLength,
  672.                                 SERA_BitsPerChar,    Config->SerialConfig->BitsPerChar,
  673.                                 SERA_StopBits,        Config->SerialConfig->StopBits,
  674.                                 SERA_BufferSize,    Config->SerialConfig->SerialBufferSize,
  675.                                 SERA_Parity,        Config->SerialConfig->Parity,
  676.                                 SERA_Handshaking,    Config->SerialConfig->HandshakingProtocol,
  677.                                 SERA_HighSpeed,        Config->SerialConfig->HighSpeed,
  678.                                 SERA_Shared,        Config->SerialConfig->Shared,
  679.                             TAG_DONE);
  680.  
  681.                                 /* Open the device driver */
  682.  
  683.                             if(!(Error = OpenSerialDevice(Config->SerialConfig->SerialDevice,Config->SerialConfig->UnitNumber)))
  684.                             {
  685.                                     /* Should we perform a DSR signal test before */
  686.                                     /* proceeding? */
  687.  
  688.                                 if(Config->SerialConfig->HandshakingProtocol == HANDSHAKING_RTSCTS_DSR)
  689.                                 {
  690.                                         /* Now check if the DSR signal is enabled. */
  691.  
  692.                                     if(GetSerialStatus() & CIAF_COMDSR)
  693.                                     {
  694.                                             /* If this is the first time the driver gets initialized, */
  695.                                             /* skip the notification message and just drop the RTS/CTS */
  696.                                             /* handshaking bit. */
  697.  
  698.                                         if(FirstInvocation)
  699.                                             UseRTS_CTS = FALSE;
  700.                                         else
  701.                                         {
  702.                                             do
  703.                                             {
  704.                                                 if(!ShowRequest(Window,LocaleString(MSG_SERIAL_NO_DSR_SIGNAL_TXT),LocaleString(MSG_SERIAL_RETRY_CANCEL_TXT)))
  705.                                                     UseRTS_CTS = FALSE;
  706.                                             }
  707.                                             while(UseRTS_CTS && (GetSerialStatus() & CIAF_COMDSR));
  708.                                         }
  709.                                     }
  710.                                 }
  711.  
  712.                                     /* Update the driver data */
  713.  
  714.                                 ResetSerialRead();
  715.                                 ResetSerialWrite();
  716.  
  717.                                     /* Set the parameters */
  718.  
  719.                                 SetFlags();
  720.  
  721.                                     /* And ask for a byte */
  722.  
  723.                                 RestartSerial();
  724.  
  725.                                 UpdateSerialJob();
  726.  
  727.                                 return(TRUE);
  728.                             }
  729.                         }
  730.                     }
  731.                     else
  732.                         ID = MSG_SERIAL_FAILED_TO_CREATE_WRITE_PORT_TXT;
  733.                 }
  734.             }
  735.             else
  736.                 ID = MSG_SERIAL_FAILED_TO_CREATE_READ_PORT_TXT;
  737.         }
  738.     }
  739.  
  740.         /* If we get here something must be wrong. */
  741.  
  742.     DeleteSerial();
  743.  
  744.         /* If we got an open error, we'll try to make it into */
  745.         /* a readable description */
  746.  
  747.     if(Error != 0)
  748.     {
  749.         STRPTR String;
  750.  
  751.         if(!(String = GetSerialError(Error,NULL)))
  752.             String = LocaleString(MSG_SERIAL_ERROR_DEVBUSY_TXT);
  753.  
  754.         LimitedSPrintf(ErrorBufferSize,ErrorBuffer,String,Config->SerialConfig->SerialDevice,Config->SerialConfig->UnitNumber);
  755.     }
  756.     else
  757.     {
  758.             /* If no open error has occured a problem must have */
  759.             /* hit us before the device was ready to open. */
  760.             /* If the error message ID is negative we'll use the */
  761.             /* default message which indicates memory allocation */
  762.             /* problems. */
  763.  
  764.         if(ID == -1)
  765.             ID = MSG_SERIAL_NOT_ENOUGH_MEMORY_TXT;
  766.  
  767.         strcpy(ErrorBuffer,LocaleString(ID));
  768.     }
  769.  
  770.     return(FALSE);
  771. }
  772.  
  773.     /* ReconfigureSerial(struct Window *Window,struct SerialSettings *SerialConfig):
  774.      *
  775.      *    Reconfigure the serial driver according to the new
  776.      *    serial settings.
  777.      */
  778.  
  779. LONG
  780. ReconfigureSerial(struct Window *Window,struct SerialSettings *SerialConfig)
  781. {
  782.     LONG Success = RECONFIGURE_NOCHANGE;
  783.  
  784.         /* Are new settings to be installed or have they already */
  785.         /* been copied to the correct locations? */
  786.  
  787.     if(CompareConfigEntries(Config->SerialConfig,SerialConfig ? SerialConfig : PrivateConfig->SerialConfig,PREF_SERIAL))
  788.     {
  789.         BOOL SameDevice = TRUE;
  790.  
  791.             /* Any new data to swap in? */
  792.  
  793.         if(SerialConfig)
  794.         {
  795.                 /* Store the previous settings. */
  796.  
  797.             SaveConfig(Config,PrivateConfig);
  798.  
  799.                 /* Install the new settings */
  800.  
  801.             PutConfigEntry(Config,SerialConfig,PREF_SERIAL);
  802.         }
  803.  
  804.             /* Any device name or unit number change? */
  805.  
  806.         if(strcmp(PrivateConfig->SerialConfig->SerialDevice,Config->SerialConfig->SerialDevice) || PrivateConfig->SerialConfig->UnitNumber != Config->SerialConfig->UnitNumber || PrivateConfig->SerialConfig->UseOwnDevUnit != Config->SerialConfig->UseOwnDevUnit)
  807.             SameDevice = FALSE;
  808.  
  809.             /* Handshaking mode changed? */
  810.  
  811.         if((PrivateConfig->SerialConfig->HandshakingProtocol == HANDSHAKING_NONE && Config->SerialConfig->HandshakingProtocol != HANDSHAKING_NONE) || (PrivateConfig->SerialConfig->HandshakingProtocol != HANDSHAKING_NONE && Config->SerialConfig->HandshakingProtocol == HANDSHAKING_NONE))
  812.             SameDevice = FALSE;
  813.  
  814.             /* Did the ODU options change? */
  815.  
  816.         if(PrivateConfig->SerialConfig->NoODUIfShared != Config->SerialConfig->NoODUIfShared && Config->SerialConfig->Shared)
  817.             SameDevice = FALSE;
  818.  
  819.             /* Is the device currently closed, i.e. should we open it? */
  820.  
  821.         if(!ReadRequest)
  822.             SameDevice = FALSE;
  823.  
  824.             /* Stop any IO activity. */
  825.  
  826.         ClearSerial();
  827.  
  828.             /* No dramatic changes? Simply change the parameters. */
  829.  
  830.         if(SameDevice)
  831.         {
  832.             LONG Error;
  833.  
  834.                 /* Did the buffer size change? */
  835.  
  836.             if(PrivateConfig->SerialConfig->SerialBufferSize != Config->SerialConfig->SerialBufferSize)
  837.             {
  838.                 STRPTR NewReadBuffer;
  839.                 STRPTR NewStripBuffer;
  840.  
  841.                     /* Allocate two new buffers */
  842.  
  843.                 NewReadBuffer    = AllocVecPooled(Config->SerialConfig->SerialBufferSize,MEMF_ANY);
  844.                 NewStripBuffer    = AllocVecPooled(Config->SerialConfig->SerialBufferSize,MEMF_ANY);
  845.  
  846.                     /* Did we get both? */
  847.  
  848.                 if(NewReadBuffer && NewStripBuffer)
  849.                 {
  850.                         /* Release the old buffers */
  851.  
  852.                     FreeVecPooled(ReadBuffer);
  853.                     FreeVecPooled(StripBuffer);
  854.  
  855.                         /* And put the new ones in */
  856.  
  857.                     ReadBuffer    = NewReadBuffer;
  858.                     StripBuffer    = NewStripBuffer;
  859.                 }
  860.                 else
  861.                 {
  862.                         /* Release whatever we had allocated */
  863.  
  864.                     FreeVecPooled(NewReadBuffer);
  865.                     FreeVecPooled(NewStripBuffer);
  866.  
  867.                         /* And change back to the old buffer size */
  868.  
  869.                     Config->SerialConfig->SerialBufferSize = PrivateConfig->SerialConfig->SerialBufferSize;
  870.                 }
  871.             }
  872.  
  873.                 /* Propagate the buffer size to the translation routines */
  874.  
  875.             Update_CR_LF_Translation();
  876.  
  877.                 /* Use new parameters */
  878.  
  879.             if(Error = SetFlags())
  880.             {
  881.                 UBYTE LocalBuffer[256];
  882.                 STRPTR String;
  883.                 BOOL Reset;
  884.  
  885.                     /* Get the error message. */
  886.  
  887.                 if(!(String = GetSerialError(Error,&Reset)))
  888.                     String = LocaleString(MSG_SERIAL_ERROR_DEVBUSY_TXT);
  889.  
  890.                     /* Build the device name/unit number string. */
  891.  
  892.                 LimitedSPrintf(sizeof(LocalBuffer),LocalBuffer,String,Config->SerialConfig->SerialDevice,Config->SerialConfig->UnitNumber);
  893.  
  894.                     /* Display the error requester. */
  895.  
  896.                 ShowRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),LocalBuffer);
  897.  
  898.                     /* Is a serial driver reset required? */
  899.  
  900.                 if(Reset)
  901.                 {
  902.                         /* Execute the reset command. */
  903.  
  904.                     DoSerialCmd(CMD_RESET);
  905.  
  906.                         /* Copy the serial driver settings */
  907.                         /* to the global configuration. */
  908.  
  909.                     CopyWriteFlags();
  910.  
  911.                         /* Also set the read request driver flags */
  912.  
  913.                     SetFlags();
  914.                 }
  915.             }
  916.  
  917.                 /* Restart read request */
  918.  
  919.             RestartSerial();
  920.         }
  921.         else
  922.         {
  923.             UBYTE LocalBuffer[256];
  924.  
  925.                 /* Shut down the serial device driver */
  926.  
  927.             DeleteSerial();
  928.  
  929.                 /* Reinitialize the serial device driver */
  930.  
  931.             if(!CreateSerial(LocalBuffer,sizeof(LocalBuffer)))
  932.             {
  933.                     /* Display the error requester */
  934.  
  935.                 ShowRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_GLOBAL_CONTINUE_TXT),LocalBuffer);
  936.  
  937.                     /* That didn't work */
  938.  
  939.                 Success = RECONFIGURE_FAILURE;
  940.             }
  941.         }
  942.     }
  943.  
  944.     return(Success);
  945. }
  946.  
  947.     /* ReopenSerial():
  948.      *
  949.      *    Reopen the serial driver.
  950.      */
  951.  
  952. VOID
  953. ReopenSerial()
  954. {
  955.     BOOL SerialClosed = TRUE;
  956.     UBYTE LocalBuffer[256];
  957.  
  958.     do
  959.     {
  960.         if(CreateSerial(LocalBuffer,sizeof(LocalBuffer)))
  961.             SerialClosed = FALSE;
  962.         else
  963.         {
  964.             switch(ShowRequest(Window,LocaleString(MSG_GLOBAL_TERM_HAS_A_PROBLEM_TXT),LocaleString(MSG_TERMMAIN_RETRY_IGNORE_QUIT_TXT),LocalBuffer))
  965.             {
  966.                 case 0:
  967.  
  968.                     MainTerminated = TRUE;
  969.                     break;
  970.  
  971.                 case 2:
  972.  
  973.                     SerialClosed = FALSE;
  974.                     break;
  975.             }
  976.         }
  977.     }
  978.     while(SerialClosed && !MainTerminated);
  979. }
  980.  
  981.     /* HandleSerialJob():
  982.      *
  983.      *    Handle the data coming in from the serial line.
  984.      */
  985.  
  986. BOOL
  987. HandleSerialJob(JobNode *UnusedJob)
  988. {
  989.     BOOL MoreData;
  990.  
  991.     if(HostReadBuffer)
  992.     {
  993.         LONG Length = XProtocolHostMon(XprIO,HostReadBuffer,0,SerialBufferSize);
  994.  
  995.         if(Translate_CR_LF && Length > 0)
  996.             Length = (*Translate_CR_LF)(HostReadBuffer,Length);
  997.  
  998.         if(Length > 0)
  999.         {
  1000.             ConProcess(HostReadBuffer,Length);
  1001.  
  1002.             if(Get_xOFF())
  1003.                 return(FALSE);
  1004.         }
  1005.  
  1006.         MoreData = TRUE;
  1007.     }
  1008.     else
  1009.         MoreData = FALSE;
  1010.  
  1011.         /* Any news? */
  1012.  
  1013.     if(CheckSerialRead())
  1014.     {
  1015.             /* Terminate the read request properly. */
  1016.  
  1017.         if(!WaitSerialRead())
  1018.         {
  1019.             ULONG Length;
  1020.  
  1021.                 /* We got another byte. */
  1022.  
  1023.             ReadBuffer[0] = ReadChar;
  1024.  
  1025.                 /* Check if there is anything waiting to be read. */
  1026.  
  1027.             if(Length = GetSerialWaiting())
  1028.             {
  1029.                 ULONG MaxSize;
  1030.  
  1031.                     /* This is how many characters fill still fit into
  1032.                      * the read buffer.
  1033.                      */
  1034.  
  1035.                 MaxSize = SerialBufferSize - 1;
  1036.  
  1037.                     /* Check if there is more data waiting
  1038.                      * than will fit into the buffer.
  1039.                      */
  1040.  
  1041.                 if(Length > MaxSize)
  1042.                     Length = MaxSize;
  1043.  
  1044.                     /* Check if there is more data waiting than
  1045.                      * the serial quantum allows.
  1046.                      */
  1047.  
  1048.                 if(Length > Config->SerialConfig->Quantum)
  1049.                     Length = Config->SerialConfig->Quantum;
  1050.  
  1051.                     /* Read the data still waiting. */
  1052.  
  1053.                 if(DoSerialRead(&ReadBuffer[1],Length))
  1054.                     Length = 0;
  1055.             }
  1056.  
  1057.                 /* One byte was added earlier. */
  1058.  
  1059.             Length++;
  1060.  
  1061.                 /* Process the data. */
  1062.  
  1063.             BytesIn += Length;
  1064.  
  1065.             (*ConTransfer)(ReadBuffer,Length);
  1066.         }
  1067.  
  1068.             /* If something is in the cache, don't overwrite
  1069.              * it by requesting another byte. Serial I/O
  1070.              * processing will be restarted when the cache
  1071.              * gets drained.
  1072.              */
  1073.  
  1074.         if(!DataHold && ProcessIO)
  1075.         {
  1076.                 /* Yes, there is more to come. */
  1077.  
  1078.             MoreData = TRUE;
  1079.  
  1080.             StartSerialRead(&ReadChar,1);
  1081.         }
  1082.     }
  1083.  
  1084.     return(MoreData);
  1085. }
  1086.  
  1087.     /* UpdateSerialJob():
  1088.      *
  1089.      *    Either activate or suspend the serial I/O job.
  1090.      */
  1091.  
  1092. VOID
  1093. UpdateSerialJob()
  1094. {
  1095.     ULONG Mask;
  1096.  
  1097.     if(!Get_xOFF() && ReadPort && ProcessIO)
  1098.         Mask = SIG_SERIAL;
  1099.     else
  1100.         Mask = NULL;
  1101.  
  1102.     if(Mask)
  1103.     {
  1104.         if(DataHold)
  1105.         {
  1106.             Mask = NULL;
  1107.  
  1108.             ActivateJob(MainJobQueue,SerialCacheJob);
  1109.         }
  1110.         else
  1111.             SuspendJob(MainJobQueue,SerialCacheJob);
  1112.     }
  1113.  
  1114.     UpdateJob(MainJobQueue,SerialJob,Mask);
  1115.  
  1116.         /* Now pick the right simplified access routines
  1117.          * for the job.
  1118.          */
  1119.  
  1120.     if(DataHold)
  1121.     {
  1122.         SerialWaitForData    = SerialCacheWaitForData;
  1123.         SerialGetWaiting    = SerialCacheGetWaiting;
  1124.         SerialRead            = SerialCacheRead;
  1125.     }
  1126.     else
  1127.     {
  1128.         SerialWaitForData    = SerialStdWaitForData;
  1129.         SerialGetWaiting    = SerialStdGetWaiting;
  1130.         SerialRead            = SerialStdRead;
  1131.     }
  1132. }
  1133.  
  1134.     /* HandleSerialCacheJob(JobNode *UnusedJob):
  1135.      *
  1136.      *    Does what HandleSerialJob() does, but picks the
  1137.      *    data from the cache.
  1138.      */
  1139.  
  1140. BOOL
  1141. HandleSerialCacheJob(JobNode *UnusedJob)
  1142. {
  1143.     STRPTR    Data = DataHold;
  1144.     LONG    Size = DataSize;
  1145.  
  1146.         /* These two are no longer valid. */
  1147.  
  1148.     DataHold = NULL;
  1149.     DataSize = 0;
  1150.  
  1151.         /* If there was anything in the buffer,
  1152.          * process it.
  1153.          */
  1154.  
  1155.     if(Size > 0)
  1156.         (*ConTransfer)(Data,Size);
  1157.  
  1158.     RestartSerial();
  1159.  
  1160.     UpdateSerialJob();
  1161.  
  1162.     return(TRUE);
  1163. }
  1164.  
  1165.  
  1166. /**********************************************************************/
  1167.  
  1168.  
  1169.     /* SerialStdWaitForData(ULONG OtherBits):
  1170.      *
  1171.      *    Wait for new data to arrive or other events to
  1172.      *    take place.
  1173.      */
  1174.  
  1175. ULONG
  1176. SerialStdWaitForData(ULONG OtherBits)
  1177. {
  1178.     return(Wait(SIG_SERIAL | OtherBits));
  1179. }
  1180.  
  1181.     /* SerialCacheWaitForData(ULONG OtherBits):
  1182.      *
  1183.      *    Checks if other events took place and always flag
  1184.      *    new serial data to be available.
  1185.      */
  1186.  
  1187. ULONG
  1188. SerialCacheWaitForData(ULONG OtherBits)
  1189. {
  1190.     return((SetSignal(0,OtherBits) & OtherBits) | SIG_SERIAL);
  1191. }
  1192.  
  1193.     /* SerialStdGetWaiting():
  1194.      *
  1195.      *    Get the number of bytes still waiting to be read.
  1196.      */
  1197.  
  1198. ULONG
  1199. SerialStdGetWaiting()
  1200. {
  1201.     return(GetSerialWaiting());
  1202. }
  1203.  
  1204.     /* SerialCacheGetWaiting():
  1205.      *
  1206.      *    Return the number of bytes still in the cache and
  1207.      *    the number of bytes waiting in the serial read
  1208.      *    buffer.
  1209.      */
  1210.  
  1211. ULONG
  1212. SerialCacheGetWaiting()
  1213. {
  1214.     return(DataSize + SerialStdGetWaiting());
  1215. }
  1216.  
  1217.     /* SerialStdRead(UBYTE *Buffer,LONG Len):
  1218.      *
  1219.      *    Reads a number of bytes from the serial line and
  1220.      *    puts them into the buffer. This routine assumes a
  1221.      *    read request had been queued earlier. It waits
  1222.      *    for the queued request to terminate, grabs the
  1223.      *    character that was read and fills the remaining
  1224.      *    buffer with the data to follow. Eventually, the
  1225.      *    read request gets queued again.
  1226.      */
  1227.  
  1228. LONG
  1229. SerialStdRead(UBYTE *Buffer,LONG Len)
  1230. {
  1231.     LONG Total;
  1232.  
  1233.         /* Wait for the read request to terminate. */
  1234.  
  1235.     WaitSerialRead();
  1236.  
  1237.         /* Put the byte into the buffer. */
  1238.  
  1239.     *Buffer++ = ReadChar;
  1240.     Len--;
  1241.  
  1242.         /* So far, one byte was read. */
  1243.  
  1244.     Total = 1;
  1245.  
  1246.         /* Any more data requested? */
  1247.  
  1248.     if(Len > 0)
  1249.     {
  1250.             /* Read the rest. */
  1251.  
  1252.         if(!DoSerialRead(Buffer,Len))
  1253.             Total += Len;
  1254.     }
  1255.  
  1256.         /* Restart the read request. */
  1257.  
  1258.     StartSerialRead(&ReadChar,1);
  1259.  
  1260.         /* Return the number of bytes read so far. */
  1261.  
  1262.     return(Total);
  1263. }
  1264.  
  1265.     /* SerialCacheRead(UBYTE *Buffer,LONG Size):
  1266.      *
  1267.      *    Read a number of bytes from the cache and the
  1268.      *    serial buffer. Switch back to normal operation
  1269.      *    if the cache is exhausted.
  1270.      */
  1271.  
  1272. LONG
  1273. SerialCacheRead(UBYTE *Buffer,LONG Size)
  1274. {
  1275.     LONG Total;
  1276.  
  1277.         /* Nothing has been read yet. */
  1278.  
  1279.     Total = 0;
  1280.  
  1281.         /* Check if there is anything left in the cache. */
  1282.  
  1283.     if(DataSize > 0)
  1284.     {
  1285.         LONG Count;
  1286.  
  1287.             /* If there is more data in the cache than
  1288.              * requested, just read the requested number
  1289.              * of bytes from it.
  1290.              */
  1291.  
  1292.         if(DataSize > Size)
  1293.             Count = Size;
  1294.         else
  1295.             Count = DataSize;
  1296.  
  1297.             /* Copy the data from the cache into the buffer. */
  1298.  
  1299.         CopyMem(DataHold,Buffer,Count);
  1300.  
  1301.             /* This is how many bytes went into the buffer so far. */
  1302.  
  1303.         Total    += Count;
  1304.  
  1305.             /* Update the buffer data. */
  1306.  
  1307.         Buffer    += Count;
  1308.         Size    -= Count;
  1309.  
  1310.             /* Update the cache data. */
  1311.  
  1312.         DataHold += Count;
  1313.         DataSize -= Count;
  1314.     }
  1315.  
  1316.         /* If no data is left in the cache, switch the read routines
  1317.          * back to the standard versions. This is done inside
  1318.          * RestartSerial().
  1319.          */
  1320.  
  1321.     if(DataSize == 0)
  1322.         RestartSerial();
  1323.  
  1324.         /* If there is still data to be read, read it from the standard
  1325.          * channel, otherwise return the number of bytes already read.
  1326.          */
  1327.  
  1328.     if(Size > 0)
  1329.         return(Total + SerialStdRead(Buffer,Size));
  1330.     else
  1331.         return(Total);
  1332. }
  1333.